home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / tcsh / dist / sh.func.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-21  |  38.0 KB  |  1,881 lines

  1. /* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.01/RCS/sh.func.c,v 3.20 1991/12/19 22:34:14 christos Exp $ */
  2. /*
  3.  * sh.func.c: csh builtin functions
  4.  */
  5. /*-
  6.  * Copyright (c) 1980, 1991 The Regents of the University of California.
  7.  * All rights reserved.
  8.  *
  9.  * Redistribution and use in source and binary forms, with or without
  10.  * modification, are permitted provided that the following conditions
  11.  * are met:
  12.  * 1. Redistributions of source code must retain the above copyright
  13.  *    notice, this list of conditions and the following disclaimer.
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in the
  16.  *    documentation and/or other materials provided with the distribution.
  17.  * 3. All advertising materials mentioning features or use of this software
  18.  *    must display the following acknowledgement:
  19.  *    This product includes software developed by the University of
  20.  *    California, Berkeley and its contributors.
  21.  * 4. Neither the name of the University nor the names of its contributors
  22.  *    may be used to endorse or promote products derived from this software
  23.  *    without specific prior written permission.
  24.  *
  25.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  26.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  29.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  31.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  34.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  35.  * SUCH DAMAGE.
  36.  */
  37. #include "sh.h"
  38.  
  39. RCSID("$Id: sh.func.c,v 3.20 1991/12/19 22:34:14 christos Exp $")
  40.  
  41. #include "ed.h"
  42. #include "tw.h"
  43. #include "tc.h"
  44.  
  45. /*
  46.  * C shell
  47.  */
  48. extern int just_signaled;
  49. extern char **environ;
  50.  
  51. extern bool MapsAreInited;
  52. extern bool NLSMapsAreInited;
  53. extern bool NoNLSRebind;
  54.  
  55. static int zlast = -1;
  56.  
  57. static    void    islogin        __P((void));
  58. static    void    reexecute    __P((struct command *));
  59. static    void    preread        __P((void));
  60. static    void    doagain        __P((void));
  61. static  char   *isrchx        __P((int));
  62. static    void    search        __P((int, int, Char *));
  63. static    int    getword        __P((Char *));
  64. static    int    keyword        __P((Char *));
  65. static    void    toend        __P((void));
  66. static    void    xecho        __P((int, Char **));
  67.  
  68. struct biltins *
  69. isbfunc(t)
  70.     struct command *t;
  71. {
  72.     register Char *cp = t->t_dcom[0];
  73.     register struct biltins *bp, *bp1, *bp2;
  74.     static struct biltins label = {"", dozip, 0, 0};
  75.     static struct biltins foregnd = {"%job", dofg1, 0, 0};
  76.     static struct biltins backgnd = {"%job &", dobg1, 0, 0};
  77.  
  78.     if (lastchr(cp) == ':') {
  79.     label.bname = short2str(cp);
  80.     return (&label);
  81.     }
  82.     if (*cp == '%') {
  83.     if (t->t_dflg & F_AMPERSAND) {
  84.         t->t_dflg &= ~F_AMPERSAND;
  85.         backgnd.bname = short2str(cp);
  86.         return (&backgnd);
  87.     }
  88.     foregnd.bname = short2str(cp);
  89.     return (&foregnd);
  90.     }
  91. #ifdef WARP
  92.     /*
  93.      * This is a perhaps kludgy way to determine if the warp builtin is to be
  94.      * acknowledged or not.  If checkwarp() fails, then we are to assume that
  95.      * the warp command is invalid, and carry on as we would handle any other
  96.      * non-builtin command.         -- JDK 2/4/88
  97.      */
  98.     if (eq(STRwarp, cp) && !checkwarp()) {
  99.     return (0);        /* this builtin disabled */
  100.     }
  101. #endif /* WARP */
  102.     /*
  103.      * Binary search Bp1 is the beginning of the current search range. Bp2 is
  104.      * one past the end.
  105.      */
  106.     for (bp1 = bfunc, bp2 = bfunc + nbfunc; bp1 < bp2;) {
  107.     register i;
  108.  
  109.     bp = bp1 + ((bp2 - bp1) >> 1);
  110.     if ((i = *cp - *bp->bname) == 0 &&
  111.         (i = Strcmp(cp, str2short(bp->bname))) == 0)
  112.         return bp;
  113.     if (i < 0)
  114.         bp2 = bp;
  115.     else
  116.         bp1 = bp + 1;
  117.     }
  118.     return (0);
  119. }
  120.  
  121. void
  122. func(t, bp)
  123.     register struct command *t;
  124.     register struct biltins *bp;
  125. {
  126.     int     i;
  127.  
  128.     xechoit(t->t_dcom);
  129.     setname(bp->bname);
  130.     i = blklen(t->t_dcom) - 1;
  131.     if (i < bp->minargs)
  132.     stderror(ERR_NAME | ERR_TOOFEW);
  133.     if (i > bp->maxargs)
  134.     stderror(ERR_NAME | ERR_TOOMANY);
  135.     (*bp->bfunct) (t->t_dcom, t);
  136. }
  137.  
  138. /*ARGSUSED*/
  139. void
  140. doonintr(v, c)
  141.     Char  **v;
  142.     struct command *c;
  143. {
  144.     register Char *cp;
  145.     register Char *vv = v[1];
  146.  
  147.     if (parintr == SIG_IGN)
  148.     return;
  149.     if (setintr && intty)
  150.     stderror(ERR_NAME | ERR_TERMINAL);
  151.     cp = gointr;
  152.     gointr = 0;
  153.     xfree((ptr_t) cp);
  154.     if (vv == 0) {
  155. #ifdef BSDSIGS
  156.     if (setintr)
  157.         (void) sigblock(sigmask(SIGINT));
  158.     else
  159.         (void) signal(SIGINT, SIG_DFL);
  160. #else /* !BSDSIGS */
  161.     if (setintr)
  162.         (void) sighold(SIGINT);
  163.     else
  164.         (void) sigset(SIGINT, SIG_DFL);
  165. #endif /* BSDSIGS */
  166.     gointr = 0;
  167.     }
  168.     else if (eq((vv = strip(vv)), STRminus)) {
  169. #ifdef BSDSIGS
  170.     (void) signal(SIGINT, SIG_IGN);
  171. #else /* !BSDSIGS */
  172.     (void) sigset(SIGINT, SIG_IGN);
  173. #endif /* BSDSIGS */
  174.     gointr = Strsave(STRminus);
  175.     }
  176.     else {
  177.     gointr = Strsave(vv);
  178. #ifdef BSDSIGS
  179.     (void) signal(SIGINT, pintr);
  180. #else /* !BSDSIGS */
  181.     (void) sigset(SIGINT, pintr);
  182. #endif /* BSDSIGS */
  183.     }
  184. }
  185.  
  186. /*ARGSUSED*/
  187. void
  188. donohup(v, c)
  189.     Char **v;
  190.     struct command *c;
  191. {
  192.     if (intty)
  193.     stderror(ERR_NAME | ERR_TERMINAL);
  194.     if (setintr == 0) {
  195.     (void) signal(SIGHUP, SIG_IGN);
  196. #ifdef CC
  197.     submit(getpid());
  198. #endif /* CC */
  199.     }
  200. }
  201.  
  202. /*ARGSUSED*/
  203. void
  204. dozip(v, c)
  205.     Char **v;
  206.     struct command *c;
  207. {
  208.     ;
  209. }
  210.  
  211. void
  212. prvars()
  213. {
  214.     plist(&shvhed);
  215. }
  216.  
  217. /*ARGSUSED*/
  218. void
  219. doalias(v, c)
  220.     register Char **v;
  221.     struct command *c;
  222. {
  223.     register struct varent *vp;
  224.     register Char *p;
  225.  
  226.     v++;
  227.     p = *v++;
  228.     if (p == 0)
  229.     plist(&aliases);
  230.     else if (*v == 0) {
  231.     vp = adrof1(strip(p), &aliases);
  232.     if (vp)
  233.         blkpr(vp->vec), xprintf("\n");
  234.     }
  235.     else {
  236.     if (eq(p, STRalias) || eq(p, STRunalias)) {
  237.         setname(short2str(p));
  238.         stderror(ERR_NAME | ERR_DANGER);
  239.     }
  240.     set1(strip(p), saveblk(v), &aliases);
  241.     tw_clear_comm_list();
  242.     }
  243. }
  244.  
  245. /*ARGSUSED*/
  246. void
  247. unalias(v, c)
  248.     Char  **v;
  249.     struct command *c;
  250. {
  251.     unset1(v, &aliases);
  252.     tw_clear_comm_list();
  253. }
  254.  
  255. /*ARGSUSED*/
  256. void
  257. dologout(v, c)
  258.     Char **v;
  259.     struct command *c;
  260. {
  261.     islogin();
  262.     goodbye(NULL, NULL);
  263. }
  264.  
  265. /*ARGSUSED*/
  266. void
  267. dologin(v, c)
  268.     Char  **v;
  269.     struct command *c;
  270. {
  271.     islogin();
  272.     rechist();
  273.     (void) signal(SIGTERM, parterm);
  274.     (void) execl(_PATH_LOGIN, "login", short2str(v[1]), NULL);
  275.     untty();
  276.     xexit(1);
  277. }
  278.  
  279.  
  280. #ifdef NEWGRP
  281. /*ARGSUSED*/
  282. void
  283. donewgrp(v, c)
  284.     Char  **v;
  285.     struct command *c;
  286. {
  287.     if (chkstop == 0 && setintr)
  288.     panystop(0);
  289.     (void) signal(SIGTERM, parterm);
  290.     (void) execl(_PATH_BIN_NEWGRP, "newgrp", short2str(v[1]), NULL);
  291.     (void) execl(_PATH_USRBIN_NEWGRP, "newgrp", short2str(v[1]), NULL);
  292.     untty();
  293.     xexit(1);
  294. }
  295. #endif /* NEWGRP */
  296.  
  297. static void
  298. islogin()
  299. {
  300.     if (chkstop == 0 && setintr)
  301.     panystop(0);
  302.     if (loginsh)
  303.     return;
  304.     stderror(ERR_NOTLOGIN);
  305. }
  306.  
  307. void
  308. doif(v, kp)
  309.     Char  **v;
  310.     struct command *kp;
  311. {
  312.     register int i;
  313.     register Char **vv;
  314.  
  315.     v++;
  316.     i = expr(&v);
  317.     vv = v;
  318.     if (*vv == NULL)
  319.     stderror(ERR_NAME | ERR_EMPTYIF);
  320.     if (eq(*vv, STRthen)) {
  321.     if (*++vv)
  322.         stderror(ERR_NAME | ERR_IMPRTHEN);
  323.     setname(short2str(STRthen));
  324.     /*
  325.      * If expression was zero, then scan to else , otherwise just fall into
  326.      * following code.
  327.      */
  328.     if (!i)
  329.         search(T_IF, 0, NULL);
  330.     return;
  331.     }
  332.     /*
  333.      * Simple command attached to this if. Left shift the node in this tree,
  334.      * munging it so we can reexecute it.
  335.      */
  336.     if (i) {
  337.     lshift(kp->t_dcom, vv - kp->t_dcom);
  338.     reexecute(kp);
  339.     donefds();
  340.     }
  341. }
  342.  
  343. /*
  344.  * Reexecute a command, being careful not
  345.  * to redo i/o redirection, which is already set up.
  346.  */
  347. static void
  348. reexecute(kp)
  349.     register struct command *kp;
  350. {
  351.     kp->t_dflg &= F_SAVE;
  352.     kp->t_dflg |= F_REPEAT;
  353.     /*
  354.      * If tty is still ours to arbitrate, arbitrate it; otherwise dont even set
  355.      * pgrp's as the jobs would then have no way to get the tty (we can't give
  356.      * it to them, and our parent wouldn't know their pgrp, etc.
  357.      */
  358.     execute(kp, (tpgrp > 0 ? tpgrp : -1), NULL, NULL);
  359. }
  360.  
  361. /*ARGSUSED*/
  362. void
  363. doelse (v, c)
  364.     Char **v;
  365.     struct command *c;
  366. {
  367.     search(T_ELSE, 0, NULL);
  368. }
  369.  
  370. /*ARGSUSED*/
  371. void
  372. dogoto(v, c)
  373.     Char  **v;
  374.     struct command *c;
  375. {
  376.     Char   *lp;
  377.  
  378.     gotolab(lp = globone(v[1], G_ERROR));
  379.     xfree((ptr_t) lp);
  380. }
  381.  
  382. void
  383. gotolab(lab)
  384.     Char *lab;
  385. {
  386.     register struct whyle *wp;
  387.     /*
  388.      * While we still can, locate any unknown ends of existing loops. This
  389.      * obscure code is the WORST result of the fact that we don't really parse.
  390.      */
  391.     zlast = T_GOTO;
  392.     for (wp = whyles; wp; wp = wp->w_next)
  393.     if (wp->w_end.type == F_SEEK && wp->w_end.f_seek == 0) {
  394.         search(T_BREAK, 0, NULL);
  395.         btell(&wp->w_end);
  396.     }
  397.     else {
  398.         bseek(&wp->w_end);
  399.     }
  400.     search(T_GOTO, 0, lab);
  401.     /*
  402.      * Eliminate loops which were exited.
  403.      */
  404.     wfree();
  405. }
  406.  
  407. /*ARGSUSED*/
  408. void
  409. doswitch(v, c)
  410.     register Char **v;
  411.     struct command *c;
  412. {
  413.     register Char *cp, *lp;
  414.  
  415.     v++;
  416.     if (!*v || *(*v++) != '(')
  417.     stderror(ERR_SYNTAX);
  418.     cp = **v == ')' ? STRNULL : *v++;
  419.     if (*(*v++) != ')')
  420.     v--;
  421.     if (*v)
  422.     stderror(ERR_SYNTAX);
  423.     search(T_SWITCH, 0, lp = globone(cp, G_ERROR));
  424.     xfree((ptr_t) lp);
  425. }
  426.  
  427. /*ARGSUSED*/
  428. void
  429. dobreak(v, c)
  430.     Char **v;
  431.     struct command *c;
  432. {
  433.     if (whyles)
  434.     toend();
  435.     else
  436.     stderror(ERR_NAME | ERR_NOTWHILE);
  437. }
  438.  
  439. /*ARGSUSED*/
  440. void
  441. doexit(v, c)
  442.     Char  **v;
  443.     struct command *c;
  444. {
  445.     if (chkstop == 0 && (intty || intact) && evalvec == 0)
  446.     panystop(0);
  447.     /*
  448.      * Don't DEMAND parentheses here either.
  449.      */
  450.     v++;
  451.     if (*v) {
  452.     set(STRstatus, putn(expr(&v)));
  453.     if (*v)
  454.         stderror(ERR_NAME | ERR_EXPRESSION);
  455.     }
  456.     btoeof();
  457.     if (intty)
  458.     (void) close(SHIN);
  459. }
  460.  
  461. /*ARGSUSED*/
  462. void
  463. doforeach(v, c)
  464.     register Char **v;
  465.     struct command *c;
  466. {
  467.     register Char *cp, *sp;
  468.     register struct whyle *nwp;
  469.  
  470.     v++;
  471.     sp = cp = strip(*v);
  472.     if (!letter(*sp))
  473.     stderror(ERR_NAME | ERR_VARBEGIN);
  474.     while (*cp && alnum(*cp))
  475.     cp++;
  476.     if (*cp)
  477.     stderror(ERR_NAME | ERR_VARALNUM);
  478.     if ((cp - sp) > MAXVARLEN)
  479.     stderror(ERR_NAME | ERR_VARTOOLONG);
  480.     cp = *v++;
  481.     if (v[0][0] != '(' || v[blklen(v) - 1][0] != ')')
  482.     stderror(ERR_NAME | ERR_NOPAREN);
  483.     v++;
  484.     gflag = 0, tglob(v);
  485.     v = globall(v);
  486.     if (v == 0)
  487.     stderror(ERR_NAME | ERR_NOMATCH);
  488.     nwp = (struct whyle *) xcalloc(1, sizeof *nwp);
  489.     nwp->w_fe = nwp->w_fe0 = v;
  490.     gargv = 0;
  491.     btell(&nwp->w_start);
  492.     nwp->w_fename = Strsave(cp);
  493.     nwp->w_next = whyles;
  494.     nwp->w_end.type = F_SEEK;
  495.     whyles = nwp;
  496.     /*
  497.      * Pre-read the loop so as to be more comprehensible to a terminal user.
  498.      */
  499.     zlast = T_FOREACH;
  500.     if (intty)
  501.     preread();
  502.     doagain();
  503. }
  504.  
  505. /*ARGSUSED*/
  506. void
  507. dowhile(v, c)
  508.     Char  **v;
  509.     struct command *c;
  510. {
  511.     register int status;
  512.     register bool again = whyles != 0 && SEEKEQ(&whyles->w_start, &lineloc) &&
  513.     whyles->w_fename == 0;
  514.  
  515.     v++;
  516.     /*
  517.      * Implement prereading here also, taking care not to evaluate the
  518.      * expression before the loop has been read up from a terminal.
  519.      */
  520.     if (intty && !again)
  521.     status = !exp0(&v, 1);
  522.     else
  523.     status = !expr(&v);
  524.     if (*v)
  525.     stderror(ERR_NAME | ERR_EXPRESSION);
  526.     if (!again) {
  527.     register struct whyle *nwp =
  528.     (struct whyle *) xcalloc(1, sizeof(*nwp));
  529.  
  530.     nwp->w_start = lineloc;
  531.     nwp->w_end.type = F_SEEK;
  532.     nwp->w_end.f_seek = 0;
  533.     nwp->w_next = whyles;
  534.     whyles = nwp;
  535.     zlast = T_WHILE;
  536.     if (intty) {
  537.         /*
  538.          * The tty preread
  539.          */
  540.         preread();
  541.         doagain();
  542.         return;
  543.     }
  544.     }
  545.     if (status)
  546.     /* We ain't gonna loop no more, no more! */
  547.     toend();
  548. }
  549.  
  550. static void
  551. preread()
  552. {
  553.     whyles->w_end.type = I_SEEK;
  554.     if (setintr)
  555. #ifdef BSDSIGS
  556.     (void) sigsetmask(sigblock((sigmask_t) 0) & ~sigmask(SIGINT));
  557. #else /* !BSDSIGS */
  558.     (void) sigrelse (SIGINT);
  559. #endif /* BSDSIGS */
  560.     search(T_BREAK, 0, NULL);        /* read the expression in */
  561.     if (setintr)
  562. #ifdef BSDSIGS
  563.     (void) sigblock(sigmask(SIGINT));
  564. #else /* !BSDSIGS */
  565.     (void) sighold(SIGINT);
  566. #endif /* BSDSIGS */
  567.     btell(&whyles->w_end);
  568. }
  569.  
  570. /*ARGSUSED*/
  571. void
  572. doend(v, c)
  573.     Char **v;
  574.     struct command *c;
  575. {
  576.     if (!whyles)
  577.     stderror(ERR_NAME | ERR_NOTWHILE);
  578.     btell(&whyles->w_end);
  579.     doagain();
  580. }
  581.  
  582. /*ARGSUSED*/
  583. void
  584. docontin(v, c)
  585.     Char **v;
  586.     struct command *c;
  587. {
  588.     if (!whyles)
  589.     stderror(ERR_NAME | ERR_NOTWHILE);
  590.     doagain();
  591. }
  592.  
  593. static void
  594. doagain()
  595. {
  596.     /* Repeating a while is simple */
  597.     if (whyles->w_fename == 0) {
  598.     bseek(&whyles->w_start);
  599.     return;
  600.     }
  601.     /*
  602.      * The foreach variable list actually has a spurious word ")" at the end of
  603.      * the w_fe list.  Thus we are at the of the list if one word beyond this
  604.      * is 0.
  605.      */
  606.     if (!whyles->w_fe[1]) {
  607.     dobreak(NULL, NULL);
  608.     return;
  609.     }
  610.     set(whyles->w_fename, Strsave(*whyles->w_fe++));
  611.     bseek(&whyles->w_start);
  612. }
  613.  
  614. void
  615. dorepeat(v, kp)
  616.     Char  **v;
  617.     struct command *kp;
  618. {
  619.     register int i;
  620.  
  621. #ifdef BSDSIGS
  622.     register sigmask_t omask = 0;
  623.  
  624. #endif /* BSDSIGS */
  625.  
  626.     i = getn(v[1]);
  627.     if (setintr)
  628. #ifdef BSDSIGS
  629.     omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT);
  630. #else /* !BSDSIGS */
  631.     (void) sighold(SIGINT);
  632. #endif /* BSDSIGS */
  633.     lshift(v, 2);
  634.     while (i > 0) {
  635.     if (setintr)
  636. #ifdef BSDSIGS
  637.         (void) sigsetmask(omask);
  638. #else /* !BSDSIGS */
  639.         (void) sigrelse (SIGINT);
  640. #endif /* BSDSIGS */
  641.     reexecute(kp);
  642.     --i;
  643.     }
  644.     donefds();
  645.     if (setintr)
  646. #ifdef BSDSIGS
  647.     (void) sigsetmask(omask);
  648. #else /* !BSDSIGS */
  649.     (void) sigrelse (SIGINT);
  650. #endif /* BSDSIGS */
  651. }
  652.  
  653. /*ARGSUSED*/
  654. void
  655. doswbrk(v, c)
  656.     Char **v;
  657.     struct command *c;
  658. {
  659.     search(T_BRKSW, 0, NULL);
  660. }
  661.  
  662. int
  663. srchx(cp)
  664.     register Char *cp;
  665. {
  666.     register struct srch *sp, *sp1, *sp2;
  667.     register i;
  668.  
  669.     /*
  670.      * Binary search Sp1 is the beginning of the current search range. Sp2 is
  671.      * one past the end.
  672.      */
  673.     for (sp1 = srchn, sp2 = srchn + nsrchn; sp1 < sp2;) {
  674.     sp = sp1 + ((sp2 - sp1) >> 1);
  675.     if ((i = *cp - *sp->s_name) == 0 &&
  676.         (i = Strcmp(cp, str2short(sp->s_name))) == 0)
  677.         return sp->s_value;
  678.     if (i < 0)
  679.         sp2 = sp;
  680.     else
  681.         sp1 = sp + 1;
  682.     }
  683.     return (-1);
  684. }
  685.  
  686. static char *
  687. isrchx(n)
  688.     register int n;
  689. {
  690.     register struct srch *sp, *sp2;
  691.  
  692.     for (sp = srchn, sp2 = srchn + nsrchn; sp < sp2; sp++)
  693.     if (sp->s_value == n)
  694.         return (sp->s_name);
  695.     return ("");
  696. }
  697.  
  698.  
  699. static Char Stype;
  700. static Char *Sgoal;
  701.  
  702. static void
  703. search(type, level, goal)
  704.     int     type;
  705.     register int level;
  706.     Char   *goal;
  707. {
  708.     Char    wordbuf[BUFSIZE];
  709.     register Char *aword = wordbuf;
  710.     register Char *cp;
  711.  
  712.     Stype = type;
  713.     Sgoal = goal;
  714.     if (type == T_GOTO) {
  715.     struct Ain a;
  716.     a.type = F_SEEK;
  717.     a.f_seek = 0;
  718.     bseek(&a);
  719.     }
  720.     do {
  721.     if (intty && fseekp == feobp && aret == F_SEEK)
  722.         printprompt(1, str2short(isrchx(type == T_BREAK ?
  723.                         zlast : type)));
  724.     /* xprintf("? "), flush(); */
  725.     aword[0] = 0;
  726.     (void) getword(aword);
  727.     switch (srchx(aword)) {
  728.  
  729.     case T_ELSE:
  730.         if (level == 0 && type == T_IF)
  731.         return;
  732.         break;
  733.  
  734.     case T_IF:
  735.         while (getword(aword))
  736.         continue;
  737.         if ((type == T_IF || type == T_ELSE) &&
  738.         eq(aword, STRthen))
  739.         level++;
  740.         break;
  741.  
  742.     case T_ENDIF:
  743.         if (type == T_IF || type == T_ELSE)
  744.         level--;
  745.         break;
  746.  
  747.     case T_FOREACH:
  748.     case T_WHILE:
  749.         if (type == T_BREAK)
  750.         level++;
  751.         break;
  752.  
  753.     case T_END:
  754.         if (type == T_BREAK)
  755.         level--;
  756.         break;
  757.  
  758.     case T_SWITCH:
  759.         if (type == T_SWITCH || type == T_BRKSW)
  760.         level++;
  761.         break;
  762.  
  763.     case T_ENDSW:
  764.         if (type == T_SWITCH || type == T_BRKSW)
  765.         level--;
  766.         break;
  767.  
  768.     case T_LABEL:
  769.         if (type == T_GOTO && getword(aword) && eq(aword, goal))
  770.         level = -1;
  771.         break;
  772.  
  773.     default:
  774.         if (type != T_GOTO && (type != T_SWITCH || level != 0))
  775.         break;
  776.         if (lastchr(aword) != ':')
  777.         break;
  778.         aword[Strlen(aword) - 1] = 0;
  779.         if ((type == T_GOTO && eq(aword, goal)) ||
  780.         (type == T_SWITCH && eq(aword, STRdefault)))
  781.         level = -1;
  782.         break;
  783.  
  784.     case T_CASE:
  785.         if (type != T_SWITCH || level != 0)
  786.         break;
  787.         (void) getword(aword);
  788.         if (lastchr(aword) == ':')
  789.         aword[Strlen(aword) - 1] = 0;
  790.         cp = strip(Dfix1(aword));
  791.         if (Gmatch(goal, cp))
  792.         level = -1;
  793.         xfree((ptr_t) cp);
  794.         break;
  795.  
  796.     case T_DEFAULT:
  797.         if (type == T_SWITCH && level == 0)
  798.         level = -1;
  799.         break;
  800.     }
  801.     (void) getword(NULL);
  802.     } while (level >= 0);
  803. }
  804.  
  805. static int
  806. getword(wp)
  807.     register Char *wp;
  808. {
  809.     register int found = 0;
  810.     register int c, d;
  811.     int     kwd = 0;
  812.     Char   *owp = wp;
  813.  
  814.     c = readc(1);
  815.     d = 0;
  816.     do {
  817.     while (c == ' ' || c == '\t')
  818.         c = readc(1);
  819.     if (c == '#')
  820.         do
  821.         c = readc(1);
  822.         while (c >= 0 && c != '\n');
  823.     if (c < 0)
  824.         goto past;
  825.     if (c == '\n') {
  826.         if (wp)
  827.         break;
  828.         return (0);
  829.     }
  830.     unreadc(c);
  831.     found = 1;
  832.     do {
  833.         c = readc(1);
  834.         if (c == '\\' && (c = readc(1)) == '\n')
  835.         c = ' ';
  836.         if (c == '\'' || c == '"')
  837.         if (d == 0)
  838.             d = c;
  839.         else if (d == c)
  840.             d = 0;
  841.         if (c < 0)
  842.         goto past;
  843.         if (wp) {
  844.         *wp++ = c;
  845.         *wp = 0;    /* end the string b4 test */
  846.         }
  847.     } while ((d || (!(kwd = keyword(owp)) && c != ' '
  848.           && c != '\t')) && c != '\n');
  849.     } while (wp == 0);
  850.  
  851.     /*
  852.      * if we have read a keyword ( "if", "switch" or "while" ) then we do not
  853.      * need to unreadc the look-ahead char
  854.      */
  855.     if (!kwd) {
  856.     unreadc(c);
  857.     if (found)
  858.         *--wp = 0;
  859.     }
  860.  
  861.     return (found);
  862.  
  863. past:
  864.     switch (Stype) {
  865.  
  866.     case T_IF:
  867.     stderror(ERR_NAME | ERR_NOTFOUND, "then/endif");
  868.  
  869.     case T_ELSE:
  870.     stderror(ERR_NAME | ERR_NOTFOUND, "endif");
  871.  
  872.     case T_BRKSW:
  873.     case T_SWITCH:
  874.     stderror(ERR_NAME | ERR_NOTFOUND, "endsw");
  875.  
  876.     case T_BREAK:
  877.     stderror(ERR_NAME | ERR_NOTFOUND, "end");
  878.  
  879.     case T_GOTO:
  880.     setname(short2str(Sgoal));
  881.     stderror(ERR_NAME | ERR_NOTFOUND, "label");
  882.  
  883.     default:
  884.     break;
  885.     }
  886.     /* NOTREACHED */
  887.     return (0);
  888. }
  889.  
  890. /*
  891.  * keyword(wp) determines if wp is one of the built-n functions if,
  892.  * switch or while. It seems that when an if statement looks like
  893.  * "if(" then getword above sucks in the '(' and so the search routine
  894.  * never finds what it is scanning for. Rather than rewrite doword, I hack
  895.  * in a test to see if the string forms a keyword. Then doword stops
  896.  * and returns the word "if" -strike
  897.  */
  898.  
  899. static int
  900. keyword(wp)
  901.     Char   *wp;
  902. {
  903.     static Char STRif[] = {'i', 'f', '\0'};
  904.     static Char STRwhile[] = {'w', 'h', 'i', 'l', 'e', '\0'};
  905.     static Char STRswitch[] = {'s', 'w', 'i', 't', 'c', 'h', '\0'};
  906.  
  907.     if (!wp)
  908.     return (0);
  909.  
  910.     if ((Strcmp(wp, STRif) == 0) || (Strcmp(wp, STRwhile) == 0)
  911.     || (Strcmp(wp, STRswitch) == 0))
  912.     return (1);
  913.  
  914.     return (0);
  915. }
  916.  
  917. static void
  918. toend()
  919. {
  920.     if (whyles->w_end.type == F_SEEK && whyles->w_end.f_seek == 0) {
  921.     search(T_BREAK, 0, NULL);
  922.     btell(&whyles->w_end);
  923.     whyles->w_end.f_seek--;
  924.     }
  925.     else {
  926.     bseek(&whyles->w_end);
  927.     }
  928.     wfree();
  929. }
  930.  
  931. void
  932. wfree()
  933. {
  934.     struct Ain    o;
  935.     struct whyle *nwp;
  936.  
  937. #ifdef FDEBUG
  938.     static char foo[] = "IAFE";
  939. #endif /* FDEBUG */
  940.  
  941.     btell(&o);
  942.  
  943. #ifdef FDEBUG
  944.     xprintf("o->type %c o->a_seek %d o->f_seek %d\n", 
  945.         foo[o.type + 1], o.a_seek, o.f_seek);
  946. #endif /* FDEBUG */
  947.  
  948.     for (; whyles; whyles = nwp) {
  949.     register struct whyle *wp = whyles;
  950.     nwp = wp->w_next;
  951.  
  952. #ifdef FDEBUG
  953.     xprintf("start->type %c start->a_seek %d start->f_seek %d\n", 
  954.         foo[wp->w_start.type+1], 
  955.         wp->w_start.a_seek, wp->w_start.f_seek);
  956.     xprintf("end->type %c end->a_seek %d end->f_seek %d\n", 
  957.         foo[wp->w_end.type + 1], wp->w_end.a_seek, wp->w_end.f_seek);
  958. #endif /* FDEBUG */
  959.  
  960.     /*
  961.      * XXX: We free loops that have different seek types.
  962.      */
  963.     if (wp->w_end.type != I_SEEK && wp->w_start.type == wp->w_end.type &&
  964.         wp->w_start.type == o.type) {
  965.         if (wp->w_end.type == F_SEEK) {
  966.         if (o.f_seek >= wp->w_start.f_seek && 
  967.             (wp->w_end.f_seek == 0 || o.f_seek < wp->w_end.f_seek))
  968.             break;
  969.         }
  970.         else {
  971.         if (o.a_seek >= wp->w_start.a_seek && 
  972.             (wp->w_end.a_seek == 0 || o.a_seek < wp->w_end.a_seek))
  973.             break;
  974.         }
  975.     }
  976.  
  977.     if (wp->w_fe0)
  978.         blkfree(wp->w_fe0);
  979.     if (wp->w_fename)
  980.         xfree((ptr_t) wp->w_fename);
  981.     xfree((ptr_t) wp);
  982.     }
  983. }
  984.  
  985. /*ARGSUSED*/
  986. void
  987. doecho(v, c)
  988.     Char  **v;
  989.     struct command *c;
  990. {
  991.     xecho(' ', v);
  992. }
  993.  
  994. /*ARGSUSED*/
  995. void
  996. doglob(v, c)
  997.     Char  **v;
  998.     struct command *c;
  999. {
  1000.     xecho(0, v);
  1001.     flush();
  1002. }
  1003.  
  1004. static void
  1005. xecho(sep, v)
  1006.     int    sep;
  1007.     register Char **v;
  1008. {
  1009.     register Char *cp;
  1010.     int     nonl = 0;
  1011.  
  1012.     if (setintr)
  1013. #ifdef BSDSIGS
  1014.     (void) sigsetmask(sigblock((sigmask_t) 0) & ~sigmask(SIGINT));
  1015. #else /* !BSDSIGS */
  1016.     (void) sigrelse (SIGINT);
  1017. #endif /* BSDSIGS */
  1018.     v++;
  1019.     if (*v == 0)
  1020.     return;
  1021.     gflag = 0, tglob(v);
  1022.     if (gflag) {
  1023.     v = globall(v);
  1024.     if (v == 0)
  1025.         stderror(ERR_NAME | ERR_NOMATCH);
  1026.     }
  1027.     else {
  1028.     v = gargv = saveblk(v);
  1029.     trim(v);
  1030.     }
  1031.     if (sep == ' ' && *v && eq(*v, STRmn))
  1032.     nonl++, v++;
  1033.     while (cp = *v++) {
  1034.     register int c;
  1035.  
  1036.     while (c = *cp++) {
  1037. #if SVID > 0
  1038. #ifndef OREO
  1039.         if (c == '\\') {
  1040.         switch (c = *cp++) {
  1041.         case 'b':
  1042.             c = '\b';
  1043.             break;
  1044.         case 'c':
  1045.             nonl = 1;
  1046.             goto done;
  1047.         case 'f':
  1048.             c = '\f';
  1049.             break;
  1050.         case 'n':
  1051.             c = '\n';
  1052.             break;
  1053.         case 'r':
  1054.             c = '\r';
  1055.             break;
  1056.         case 't':
  1057.             c = '\t';
  1058.             break;
  1059.         case 'v':
  1060.             c = '\v';
  1061.             break;
  1062.         case '\\':
  1063.             c = '\\';
  1064.             break;
  1065.         case '0':
  1066.             c = 0;
  1067.             if (*cp >= '0' && *cp < '8')
  1068.             c = c * 8 + *cp++ - '0';
  1069.             if (*cp >= '0' && *cp < '8')
  1070.             c = c * 8 + *cp++ - '0';
  1071.             if (*cp >= '0' && *cp < '8')
  1072.             c = c * 8 + *cp++ - '0';
  1073.             break;
  1074.         case '\0':
  1075.             c = *--cp;
  1076.             break;
  1077.         default:
  1078.             xputchar('\\' | QUOTE);
  1079.             break;
  1080.         }
  1081.         }
  1082. #endif /* OREO */
  1083. #endif /* SVID > 0 */
  1084.         xputchar(c | QUOTE);
  1085.  
  1086.     }
  1087.     if (*v)
  1088.         xputchar(sep | QUOTE);
  1089.     }
  1090. #if SVID > 0
  1091. #ifndef OREO
  1092. done:
  1093. #endif /* OREO */
  1094. #endif /* SVID > 0 */
  1095.     if (sep && nonl == 0)
  1096.     xputchar('\n');
  1097.     else
  1098.     flush();
  1099.     if (setintr)
  1100. #ifdef BSDSIGS
  1101.     (void) sigblock(sigmask(SIGINT));
  1102. #else /* !BSDSIGS */
  1103.     (void) sighold(SIGINT);
  1104. #endif /* BSDSIGS */
  1105.     if (gargv)
  1106.     blkfree(gargv), gargv = 0;
  1107. }
  1108.  
  1109. /* from "Karl Berry." <karl%mote.umb.edu@relay.cs.net> -- for NeXT things
  1110.    (and anything else with a modern compiler) */
  1111.  
  1112. /*ARGSUSED*/
  1113. void
  1114. dosetenv(v, c)
  1115.     register Char **v;
  1116.     struct command *c;
  1117. {
  1118.     Char   *vp, *lp;
  1119.  
  1120.     v++;
  1121.     if ((vp = *v++) == 0) {
  1122.     register Char **ep;
  1123.  
  1124.     if (setintr)
  1125. #ifdef BSDSIGS
  1126.         (void) sigsetmask(sigblock((sigmask_t) 0) & ~sigmask(SIGINT));
  1127. #else /* !BSDSIGS */
  1128.         (void) sigrelse (SIGINT);
  1129. #endif /* BSDSIGS */
  1130.     for (ep = STR_environ; *ep; ep++)
  1131.         xprintf("%s\n", short2str(*ep));
  1132.     return;
  1133.     }
  1134.     if ((lp = *v++) == 0)
  1135.     lp = STRNULL;
  1136.     Setenv(vp, lp = globone(lp, G_APPEND));
  1137.     if (eq(vp, STRPATH)) {
  1138.     importpath(lp);
  1139.     dohash(NULL, NULL);
  1140.     }
  1141. #ifdef apollo
  1142.     else if (eq(vp, STRSYSTYPE))
  1143.     dohash(NULL, NULL);
  1144. #endif /* apollo */
  1145.     else if (eq(vp, STRLANG) || eq(vp, STRLC_CTYPE)) {
  1146. #ifdef NLS
  1147.     int     k;
  1148.  
  1149.     (void) setlocale(LC_ALL, "");
  1150.     for (k = 0200; k <= 0377 && !Isprint(k); k++);
  1151.     AsciiOnly = k > 0377;
  1152. #else /* !NLS */
  1153.     AsciiOnly = 0;
  1154. #endif /* NLS */
  1155.     NLSMapsAreInited = 0;
  1156.     ed_Init();
  1157.     if (MapsAreInited && !NLSMapsAreInited)
  1158.         (void) ed_InitNLSMaps();
  1159.     }
  1160.     else if (eq(vp, STRNOREBIND)) {
  1161.     NoNLSRebind = 1;
  1162.     }
  1163. #ifdef SIG_WINDOW
  1164.     else if ((eq(lp, STRNULL) &&
  1165.           (eq(vp, STRLINES) || eq(vp, STRCOLUMNS))) ||
  1166.          eq(vp, STRTERMCAP)) {
  1167.     check_window_size(1);
  1168.     }
  1169. #endif /* SIG_WINDOW */
  1170.     xfree((ptr_t) lp);
  1171. }
  1172.  
  1173. /*ARGSUSED*/
  1174. void
  1175. dounsetenv(v, c)
  1176.     register Char **v;
  1177.     struct command *c;
  1178. {
  1179.     Char  **ep, *p, *n;
  1180.     int     i, maxi;
  1181.     static Char *name = NULL;
  1182.  
  1183.     if (name)
  1184.     xfree((ptr_t) name);
  1185.     /*
  1186.      * Find the longest environment variable
  1187.      */
  1188.     for (maxi = 0, ep = STR_environ; *ep; ep++) {
  1189.     for (i = 0, p = *ep; *p && *p != '='; p++, i++);
  1190.     if (i > maxi)
  1191.         maxi = i;
  1192.     }
  1193.  
  1194.     name = (Char *) xmalloc((size_t) (maxi + 1) * sizeof(Char));
  1195.  
  1196.     while (++v && *v) 
  1197.     for (maxi = 1; maxi;)
  1198.         for (maxi = 0, ep = STR_environ; *ep; ep++) {
  1199.         for (n = name, p = *ep; *p && *p != '='; *n++ = *p++);
  1200.         *n = '\0';
  1201.         if (!Gmatch(name, *v))
  1202.             continue;
  1203.         maxi = 1;
  1204.         if (eq(name, STRNOREBIND))
  1205.             NoNLSRebind = 0;
  1206. #ifdef apollo
  1207.         else if (eq(name, STRSYSTYPE))
  1208.             dohash(NULL, NULL);
  1209. #endif /* apollo */
  1210.         else if (eq(name, STRLANG) || eq(name, STRLC_CTYPE)) {
  1211. #ifdef NLS
  1212.             int     k;
  1213.  
  1214.             (void) setlocale(LC_ALL, "");
  1215.             for (k = 0200; k <= 0377 && !Isprint(k); k++);
  1216.             AsciiOnly = k > 0377;
  1217. #else /* !NLS */
  1218.             AsciiOnly = getenv("LANG") == NULL &&
  1219.             getenv("LC_CTYPE") == NULL;
  1220. #endif /* NLS */
  1221.             NLSMapsAreInited = 0;
  1222.             ed_Init();
  1223.             if (MapsAreInited && !NLSMapsAreInited)
  1224.             (void) ed_InitNLSMaps();
  1225.  
  1226.         }
  1227.         /*
  1228.          * Delete name, and start again cause the environment changes
  1229.          */
  1230.         Unsetenv(name);
  1231.         break;
  1232.         }
  1233.     xfree((ptr_t) name); name = NULL;
  1234. }
  1235.  
  1236. void
  1237. Setenv(name, val)
  1238.     Char   *name, *val;
  1239. {
  1240. #ifdef SETENV_IN_LIB
  1241. /*
  1242.  * XXX: This does not work right, since tcsh cannot track changes to
  1243.  * the environment this way. (the builtin setenv without arguments does
  1244.  * not print the right stuff neither does unsetenv). This was for Mach,
  1245.  * it is not needed anymore.
  1246.  */
  1247. #undef setenv
  1248.     char    nameBuf[BUFSIZE];
  1249.     char   *cname = short2str(name);
  1250.  
  1251.     if (cname == NULL)
  1252.     return;
  1253.     (void) strcpy(nameBuf, cname);
  1254.     setenv(nameBuf, short2str(val), 1);
  1255. #else /* !SETENV_IN_LIB */
  1256.     register Char **ep = STR_environ;
  1257.     register Char *cp, *dp;
  1258.     Char   *blk[2];
  1259.     Char  **oep = ep;
  1260.  
  1261.  
  1262.     for (; *ep; ep++) {
  1263.     for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++)
  1264.         continue;
  1265.     if (*cp != 0 || *dp != '=')
  1266.         continue;
  1267.     cp = Strspl(STRequal, val);
  1268.     xfree((ptr_t) * ep);
  1269.     *ep = strip(Strspl(name, cp));
  1270.     xfree((ptr_t) cp);
  1271.     blkfree((Char **) environ);
  1272.     environ = short2blk(STR_environ);
  1273.     return;
  1274.     }
  1275.     cp = Strspl(name, STRequal);
  1276.     blk[0] = strip(Strspl(cp, val));
  1277.     xfree((ptr_t) cp);
  1278.     blk[1] = 0;
  1279.     STR_environ = blkspl(STR_environ, blk);
  1280.     blkfree((Char **) environ);
  1281.     environ = short2blk(STR_environ);
  1282.     xfree((ptr_t) oep);
  1283. #endif /* SETENV_IN_LIB */
  1284. }
  1285.  
  1286. void
  1287. Unsetenv(name)
  1288.     Char   *name;
  1289. {
  1290.     register Char **ep = STR_environ;
  1291.     register Char *cp, *dp;
  1292.     Char  **oep = ep;
  1293.  
  1294.     for (; *ep; ep++) {
  1295.     for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++)
  1296.         continue;
  1297.     if (*cp != 0 || *dp != '=')
  1298.         continue;
  1299.     cp = *ep;
  1300.     *ep = 0;
  1301.     STR_environ = blkspl(STR_environ, ep + 1);
  1302.     environ = short2blk(STR_environ);
  1303.     *ep = cp;
  1304.     xfree((ptr_t) cp);
  1305.     xfree((ptr_t) oep);
  1306.     return;
  1307.     }
  1308. }
  1309.  
  1310. /*ARGSUSED*/
  1311. void
  1312. doumask(v, c)
  1313.     register Char **v;
  1314.     struct command *c;
  1315. {
  1316.     register Char *cp = v[1];
  1317.     register int i;
  1318.  
  1319.     if (cp == 0) {
  1320.     i = umask(0);
  1321.     (void) umask(i);
  1322.     xprintf("%o\n", i);
  1323.     return;
  1324.     }
  1325.     i = 0;
  1326.     while (Isdigit(*cp) && *cp != '8' && *cp != '9')
  1327.     i = i * 8 + *cp++ - '0';
  1328.     if (*cp || i < 0 || i > 0777)
  1329.     stderror(ERR_NAME | ERR_MASK);
  1330.     (void) umask(i);
  1331. }
  1332.  
  1333. #ifndef HAVENOLIMIT
  1334. # ifndef BSDTIMES
  1335.    typedef long RLIM_TYPE;
  1336. #  ifndef RLIM_INFINITY
  1337.     extern RLIM_TYPE ulimit();
  1338. #   define RLIM_INFINITY 0x003fffff
  1339. #   define RLIMIT_FSIZE 1
  1340. #  endif /* RLIM_INFINITY */
  1341. #  ifdef aiws
  1342. #   define toset(a) (((a) == 3) ? 1004 : (a) + 1)
  1343. #   define RLIMIT_DATA    3
  1344. #   define RLIMIT_STACK 1005
  1345. #  else /* aiws */
  1346. #   define toset(a) ((a) + 1)
  1347. #  endif /* aiws */
  1348. # else /* BSDTIMES */
  1349.    typedef int RLIM_TYPE;
  1350. # endif /* BSDTIMES */
  1351.  
  1352.  
  1353. static struct limits {
  1354.     int     limconst;
  1355.     char   *limname;
  1356.     int     limdiv;
  1357.     char   *limscale;
  1358. }       limits[] = {
  1359.  
  1360. # ifdef RLIMIT_CPU
  1361.     RLIMIT_CPU,     "cputime",    1,    "seconds",
  1362. # endif /* RLIMIT_CPU */
  1363.  
  1364. # ifdef RLIMIT_FSIZE
  1365. #  ifndef aiws
  1366.     RLIMIT_FSIZE,     "filesize",    1024,    "kbytes",
  1367. #  else
  1368.     RLIMIT_FSIZE,     "filesize",    512,    "blocks",
  1369. #  endif /* aiws */
  1370. # endif /* RLIMIT_FSIZE */
  1371.  
  1372. # ifdef RLIMIT_DATA
  1373.     RLIMIT_DATA,     "datasize",    1024,    "kbytes",
  1374. # endif /* RLIMIT_DATA */
  1375.  
  1376. # ifdef RLIMIT_STACK
  1377. #  ifndef aiws
  1378.     RLIMIT_STACK,     "stacksize",    1024,    "kbytes",
  1379. #  else
  1380.     RLIMIT_STACK,     "stacksize",    1024 * 1024,    "kbytes",
  1381. #  endif /* aiws */
  1382. # endif /* RLIMIT_STACK */
  1383.  
  1384. # ifdef RLIMIT_CORE
  1385.     RLIMIT_CORE,     "coredumpsize",    1024,    "kbytes",
  1386. # endif /* RLIMIT_CORE */
  1387.  
  1388. # ifdef RLIMIT_RSS
  1389.     RLIMIT_RSS,     "memoryuse",    1024,    "kbytes",
  1390. # endif /* RLIMIT_RSS */
  1391.  
  1392. # ifdef RLIMIT_NOFILE
  1393.     RLIMIT_NOFILE,     "descriptors", 1,    "",
  1394. # endif /* RLIMIT_NOFILE */
  1395.  
  1396. # ifdef RLIMIT_CONCUR
  1397.     RLIMIT_CONCUR,     "concurrency", 1,    "thread(s)",
  1398. # endif /* RLIMIT_CONCUR */
  1399.  
  1400. # ifdef RLIMIT_MEMLOCK
  1401.     RLIMIT_MEMLOCK,    "memorylocked",    1024,    "kbytes",
  1402. # endif /* RLIMIT_MEMLOCK */
  1403.  
  1404. # ifdef RLIMIT_NPROC
  1405.     RLIMIT_NPROC,    "maxproc",    1,    "",
  1406. # endif /* RLIMIT_NPROC */
  1407.  
  1408. # ifdef RLIMIT_OFILE
  1409.     RLIMIT_OFILE,    "openfiles",    1,    "",
  1410. # endif /* RLIMIT_OFILE */
  1411.  
  1412.     -1,         NULL,         0,     NULL
  1413. };
  1414.  
  1415. static struct limits *findlim();
  1416. static RLIM_TYPE getval();
  1417. static void limtail();
  1418. static void plim();
  1419. static int setlim();
  1420.  
  1421. #if defined(convex) || defined(__convex__)
  1422. static  RLIM_TYPE
  1423. restrict_limit(value)
  1424.     double  value;
  1425. {
  1426.     /*
  1427.      * is f too large to cope with? return the maximum or minimum int
  1428.      */
  1429.     if (value > (double) INT_MAX)
  1430.     return (INT_MAX);
  1431.     else if (value < (double) INT_MIN)
  1432.     return (INT_MIN);
  1433.     else
  1434.     return ((int) value);
  1435. }
  1436. #endif /* convex */
  1437.  
  1438.  
  1439. static struct limits *
  1440. findlim(cp)
  1441.     Char   *cp;
  1442. {
  1443.     register struct limits *lp, *res;
  1444.  
  1445.     res = (struct limits *) NULL;
  1446.     for (lp = limits; lp->limconst >= 0; lp++)
  1447.     if (prefix(cp, str2short(lp->limname))) {
  1448.         if (res)
  1449.         stderror(ERR_NAME | ERR_AMBIG);
  1450.         res = lp;
  1451.     }
  1452.     if (res)
  1453.     return (res);
  1454.     stderror(ERR_NAME | ERR_LIMIT);
  1455.     /* NOTREACHED */
  1456.     return (0);
  1457. }
  1458.  
  1459. /*ARGSUSED*/
  1460. void
  1461. dolimit(v, c)
  1462.     register Char **v;
  1463.     struct command *c;
  1464. {
  1465.     register struct limits *lp;
  1466.     register RLIM_TYPE limit;
  1467.     char    hard = 0;
  1468.  
  1469.     v++;
  1470.     if (*v && eq(*v, STRmh)) {
  1471.     hard = 1;
  1472.     v++;
  1473.     }
  1474.     if (*v == 0) {
  1475.     for (lp = limits; lp->limconst >= 0; lp++)
  1476.         plim(lp, hard);
  1477.     return;
  1478.     }
  1479.     lp = findlim(v[0]);
  1480.     if (v[1] == 0) {
  1481.     plim(lp, hard);
  1482.     return;
  1483.     }
  1484.     limit = getval(lp, v + 1);
  1485.     if (setlim(lp, hard, limit) < 0)
  1486.     stderror(ERR_SILENT);
  1487. }
  1488.  
  1489. static  RLIM_TYPE
  1490. getval(lp, v)
  1491.     register struct limits *lp;
  1492.     Char  **v;
  1493. {
  1494. # if defined(convex) || defined(__convex__)
  1495.     RLIM_TYPE restrict_limit();
  1496. # endif /* convex */
  1497.  
  1498.     register float f;
  1499.     double  atof();
  1500.     static int lmin = 0x80000000, lmax = 0x7fffffff;
  1501.     Char   *cp = *v++;
  1502.  
  1503.     f = atof(short2str(cp));
  1504.  
  1505. # if defined(convex) || defined(__convex__)
  1506.     /*
  1507.      * is f too large to cope with. limit f to minint, maxint  - X-6768 by
  1508.      * strike
  1509.      */
  1510.     if ((f < (double) INT_MIN) || (f > (double) INT_MAX)) {
  1511.     stderror(ERR_NAME | ERR_TOOLARGE);
  1512.     }
  1513. # endif /* convex */
  1514.  
  1515.     while (Isdigit(*cp) || *cp == '.' || *cp == 'e' || *cp == 'E')
  1516.     cp++;
  1517.     if (*cp == 0) {
  1518.     if (*v == 0)
  1519. # if defined(convex) || defined(__convex__)
  1520.         return ((RLIM_TYPE) restrict_limit((f + 0.5) * lp->limdiv));
  1521. # else /* convex */
  1522.         return ((RLIM_TYPE) ((f + 0.5) * lp->limdiv));
  1523. # endif /* convex */
  1524.     cp = *v;
  1525.     }
  1526.     switch (*cp) {
  1527. # ifdef RLIMIT_CPU
  1528.     case ':':
  1529.     if (lp->limconst != RLIMIT_CPU)
  1530.         goto badscal;
  1531. #  if defined(convex) || defined(__convex__)
  1532.     return ((RLIM_TYPE)
  1533.         restrict_limit((f * 60.0 + atof(short2str(cp + 1)))));
  1534. #  else /* convex */
  1535.     return ((RLIM_TYPE) (f * 60.0 + atof(short2str(cp + 1))));
  1536. #  endif /* convex */
  1537.     case 'h':
  1538.     if (lp->limconst != RLIMIT_CPU)
  1539.         goto badscal;
  1540.     limtail(cp, "hours");
  1541.     f *= 3600.0;
  1542.     break;
  1543.     case 'm':
  1544.     if (lp->limconst == RLIMIT_CPU) {
  1545.         limtail(cp, "minutes");
  1546.         f *= 60.0;
  1547.         break;
  1548.     }
  1549.     *cp = 'm';
  1550.     limtail(cp, "megabytes");
  1551.     f *= 1024.0 * 1024.0;
  1552.     break;
  1553.     case 's':
  1554.     if (lp->limconst != RLIMIT_CPU)
  1555.         goto badscal;
  1556.     limtail(cp, "seconds");
  1557.     break;
  1558. # endif /* RLIMIT_CPU */
  1559.     case 'M':
  1560. # ifdef RLIMIT_CPU
  1561.     if (lp->limconst == RLIMIT_CPU)
  1562.         goto badscal;
  1563. # endif /* RLIMIT_CPU */
  1564.     *cp = 'm';
  1565.     limtail(cp, "megabytes");
  1566.     f *= 1024.0 * 1024.0;
  1567.     break;
  1568.     case 'k':
  1569. # ifdef RLIMIT_CPU
  1570.     if (lp->limconst == RLIMIT_CPU)
  1571.         goto badscal;
  1572. # endif /* RLIMIT_CPU */
  1573.     limtail(cp, "kbytes");
  1574.     f *= 1024.0;
  1575.     break;
  1576.     case 'b':
  1577. # ifdef RLIMIT_CPU
  1578.     if (lp->limconst == RLIMIT_CPU)
  1579.         goto badscal;
  1580. # endif /* RLIMIT_CPU */
  1581.     limtail(cp, "blocks");
  1582.     f *= 512.0;
  1583.     break;
  1584.     case 'u':
  1585.     limtail(cp, "unlimited");
  1586.     return (RLIM_INFINITY);
  1587.     default:
  1588. # ifdef RLIMIT_CPU
  1589. badscal:
  1590. # endif /* RLIMIT_CPU */
  1591.     stderror(ERR_NAME | ERR_SCALEF);
  1592.     }
  1593. # if defined(convex) || defined(__convex__)
  1594.     return ((RLIM_TYPE) restrict_limit((f + 0.5)));
  1595. # else
  1596.     f += 0.5;
  1597.     if (f > (float) lmax)
  1598.     return lmax;
  1599.     else if (f < (float) lmin)
  1600.     return lmin;
  1601.     else
  1602.     return ((RLIM_TYPE) f);
  1603. # endif /* convex */
  1604. }
  1605.  
  1606. static void
  1607. limtail(cp, str)
  1608.     Char   *cp;
  1609.     char   *str;
  1610. {
  1611.     while (*cp && *cp == *str)
  1612.     cp++, str++;
  1613.     if (*cp)
  1614.     stderror(ERR_BADSCALE, str);
  1615. }
  1616.  
  1617.  
  1618. /*ARGSUSED*/
  1619. static void
  1620. plim(lp, hard)
  1621.     register struct limits *lp;
  1622.     Char    hard;
  1623. {
  1624. # ifdef BSDTIMES
  1625.     struct rlimit rlim;
  1626. # endif /* BSDTIMES */
  1627.     RLIM_TYPE limit;
  1628.  
  1629.     xprintf("%s \t", lp->limname);
  1630.  
  1631. # ifndef BSDTIMES
  1632.     limit = ulimit(lp->limconst, 0);
  1633. #  ifdef aiws
  1634.     if (lp->limconst == RLIMIT_DATA)
  1635.     limit -= 0x20000000;
  1636. #  endif /* aiws */
  1637. # else /* BSDTIMES */
  1638.     (void) getrlimit(lp->limconst, &rlim);
  1639.     limit = hard ? rlim.rlim_max : rlim.rlim_cur;
  1640. # endif /* BSDTIMES */
  1641.  
  1642.     if (limit == RLIM_INFINITY)
  1643.     xprintf("unlimited");
  1644. # ifdef RLIMIT_CPU
  1645.     else if (lp->limconst == RLIMIT_CPU)
  1646.     psecs((long) limit);
  1647. # endif /* RLIMIT_CPU */
  1648.     else
  1649. # ifndef BSDTIMES
  1650.     if (lp->limconst == RLIMIT_FSIZE)
  1651.     /*
  1652.      * Christos: filesize comes in 512 blocks. we divide by 2 to get 1024
  1653.      * blocks. Note we cannot pre-multiply cause we might overflow (A/UX)
  1654.      */
  1655.     xprintf("%ld %s", (long) (limit / (lp->limdiv == 1024 ? 2 : 1)), 
  1656.             lp->limscale);
  1657.     else
  1658. # endif /* BSDTIMES */
  1659.     xprintf("%ld %s", (long) (limit / lp->limdiv), lp->limscale);
  1660.     xprintf("\n");
  1661. }
  1662.  
  1663. /*ARGSUSED*/
  1664. void
  1665. dounlimit(v, c)
  1666.     register Char **v;
  1667.     struct command *c;
  1668. {
  1669.     register struct limits *lp;
  1670.     int     lerr = 0;
  1671.     Char    hard = 0;
  1672.  
  1673.     v++;
  1674.     if (*v && eq(*v, STRmh)) {
  1675.     hard = 1;
  1676.     v++;
  1677.     }
  1678.     if (*v == 0) {
  1679.     for (lp = limits; lp->limconst >= 0; lp++)
  1680.         if (setlim(lp, hard, (RLIM_TYPE) RLIM_INFINITY) < 0)
  1681.         lerr++;
  1682.     if (lerr)
  1683.         stderror(ERR_SILENT);
  1684.     return;
  1685.     }
  1686.     while (*v) {
  1687.     lp = findlim(*v++);
  1688.     if (setlim(lp, hard, (RLIM_TYPE) RLIM_INFINITY) < 0)
  1689.         stderror(ERR_SILENT);
  1690.     }
  1691. }
  1692.  
  1693. static int
  1694. setlim(lp, hard, limit)
  1695.     register struct limits *lp;
  1696.     Char    hard;
  1697.     RLIM_TYPE limit;
  1698. {
  1699. # ifdef BSDTIMES
  1700.     struct rlimit rlim;
  1701.  
  1702.     (void) getrlimit(lp->limconst, &rlim);
  1703.  
  1704.     if (hard)
  1705.     rlim.rlim_max = limit;
  1706.     else if (limit == RLIM_INFINITY && geteuid() != 0)
  1707.     rlim.rlim_cur = rlim.rlim_max;
  1708.     else
  1709.     rlim.rlim_cur = limit;
  1710.  
  1711.     if (setrlimit(lp->limconst, &rlim) < 0) {
  1712. # else /* BSDTIMES */
  1713.     if (limit != RLIM_INFINITY && lp->limconst == RLIMIT_FSIZE)
  1714.     limit /= 512;
  1715. # ifdef aiws
  1716.     if (lp->limconst == RLIMIT_DATA)
  1717.     limit += 0x20000000;
  1718. # endif /* aiws */
  1719.     if (ulimit(toset(lp->limconst), limit) < 0) {
  1720. # endif /* BSDTIMES */
  1721.     xprintf("%s: %s: Can't %s%s limit\n", bname, lp->limname,
  1722.         limit == RLIM_INFINITY ? "remove" : "set",
  1723.         hard ? " hard" : "");
  1724.     return (-1);
  1725.     }
  1726.     return (0);
  1727. }
  1728.  
  1729. #endif /* !HAVENOLIMIT */
  1730.  
  1731. /*ARGSUSED*/
  1732. void
  1733. dosuspend(v, c)
  1734.     Char **v;
  1735.     struct command *c;
  1736. {
  1737.     int     ctpgrp;
  1738.  
  1739.     sigret_t(*old) ();
  1740.  
  1741.     if (loginsh)
  1742.     stderror(ERR_SUSPLOG);
  1743.     untty();
  1744.  
  1745. #ifdef BSDJOBS
  1746.     old = signal(SIGTSTP, SIG_DFL);
  1747.     (void) kill(0, SIGTSTP);
  1748.     /* the shell stops here */
  1749.     (void) signal(SIGTSTP, old);
  1750. #else /* !BSDJOBS */
  1751.     stderror(ERR_JOBCONTROL);
  1752. #endif /* BSDJOBS */
  1753.  
  1754. #ifdef BSDJOBS
  1755.     if (tpgrp != -1) {
  1756. retry:
  1757.     ctpgrp = tcgetpgrp(FSHTTY);
  1758.     if (ctpgrp != opgrp) {
  1759.         old = signal(SIGTTIN, SIG_DFL);
  1760.         (void) kill(0, SIGTTIN);
  1761.         (void) signal(SIGTTIN, old);
  1762.         goto retry;
  1763.     }
  1764.     (void) setpgid(0, shpgrp);
  1765.     (void) tcsetpgrp(FSHTTY, shpgrp);
  1766.     }
  1767. #endif /* BSDJOBS */
  1768.     (void) setdisc(FSHTTY);
  1769. }
  1770.  
  1771. /* This is the dreaded EVAL built-in.
  1772.  *   If you don't fiddle with file descriptors, and reset didfds,
  1773.  *   this command will either ignore redirection inside or outside
  1774.  *   its aguments, e.g. eval "date >x"  vs.  eval "date" >x
  1775.  *   The stuff here seems to work, but I did it by trial and error rather
  1776.  *   than really knowing what was going on.  If tpgrp is zero, we are
  1777.  *   probably a background eval, e.g. "eval date &", and we want to
  1778.  *   make sure that any processes we start stay in our pgrp.
  1779.  *   This is also the case for "time eval date" -- stay in same pgrp.
  1780.  *   Otherwise, under stty tostop, processes will stop in the wrong
  1781.  *   pgrp, with no way for the shell to get them going again.  -IAN!
  1782.  */
  1783.  
  1784. static Char **gv = NULL;
  1785.  
  1786. /*ARGSUSED*/
  1787. void
  1788. doeval(v, c)
  1789.     Char  **v;
  1790.     struct command *c;
  1791. {
  1792.     Char  **oevalvec;
  1793.     Char   *oevalp;
  1794.     int     odidfds;
  1795. #ifndef FIOCLEX
  1796.     int     odidcch;
  1797. #endif /* FIOCLEX */
  1798.     jmp_buf osetexit;
  1799.     int     my_reenter;
  1800.     Char  **savegv;
  1801.     int     saveIN, saveOUT, saveDIAG;
  1802.     int     oSHIN, oSHOUT, oSHDIAG;
  1803.  
  1804.     oevalvec = evalvec;
  1805.     oevalp = evalp;
  1806.     odidfds = didfds;
  1807. #ifndef FIOCLEX
  1808.     odidcch = didcch;
  1809. #endif /* FIOCLEX */
  1810.     oSHIN = SHIN;
  1811.     oSHOUT = SHOUT;
  1812.     oSHDIAG = SHDIAG;
  1813.  
  1814.     savegv = gv;
  1815.  
  1816.     v++;
  1817.     if (*v == 0)
  1818.     return;
  1819.     gflag = 0, tglob(v);
  1820.     if (gflag) {
  1821.     gv = v = globall(v);
  1822.     gargv = 0;
  1823.     if (v == 0)
  1824.         stderror(ERR_NOMATCH);
  1825.     v = copyblk(v);
  1826.     }
  1827.     else {
  1828.     gv = NULL;
  1829.     v = copyblk(v);
  1830.     trim(v);
  1831.     }
  1832.  
  1833.     saveIN = dcopy(SHIN, -1);
  1834.     saveOUT = dcopy(SHOUT, -1);
  1835.     saveDIAG = dcopy(SHDIAG, -1);
  1836.  
  1837.     getexit(osetexit);
  1838.  
  1839.     /* PWP: setjmp/longjmp bugfix for optimizing compilers */
  1840. #ifdef cray
  1841.     my_reenter = 1;             /* assume non-zero return val */
  1842.     if (setexit() == 0) {
  1843.     my_reenter = 0;         /* Oh well, we were wrong */
  1844. #else /* !cray */
  1845.     if ((my_reenter = setexit()) == 0) {
  1846. #endif /* cray */
  1847.     evalvec = v;
  1848.     evalp = 0;
  1849.     SHIN = dcopy(0, -1);
  1850.     SHOUT = dcopy(1, -1);
  1851.     SHDIAG = dcopy(2, -1);
  1852. #ifndef FIOCLEX
  1853.     didcch = 0;
  1854. #endif /* FIOCLEX */
  1855.     didfds = 0;
  1856.     process(0);
  1857.     }
  1858.  
  1859.     evalvec = oevalvec;
  1860.     evalp = oevalp;
  1861.     doneinp = 0;
  1862. #ifndef FIOCLEX
  1863.     didcch = odidcch;
  1864. #endif /* FIOCLEX */
  1865.     didfds = odidfds;
  1866.     (void) close(SHIN);
  1867.     (void) close(SHOUT);
  1868.     (void) close(SHDIAG);
  1869.     SHIN = dmove(saveIN, oSHIN);
  1870.     SHOUT = dmove(saveOUT, oSHOUT);
  1871.     SHDIAG = dmove(saveDIAG, oSHDIAG);
  1872.  
  1873.     if (gv)
  1874.     blkfree(gv);
  1875.  
  1876.     gv = savegv;
  1877.     resexit(osetexit);
  1878.     if (my_reenter)
  1879.     stderror(ERR_SILENT);
  1880. }
  1881.